package com.imooc.ras2;

import cn.hutool.core.text.AntPathMatcher;
import cn.hutool.http.ContentType;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;


/**
 * Description: 过滤器
 * Author: gzj
 * Date: 2024/4/24 13:41
 */
@Slf4j
public class ResponseDataFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest requests =  (HttpServletRequest) request;
       //与前端约定小程序不用加解密
        String isRsa = requests.getHeader("isRsa");
        if(StringUtils.isNotBlank(isRsa)){
            chain.doFilter(request, response);
            return;
        }

        String uri = ((HttpServletRequest) request).getRequestURI();
//        如果是非 multipart/form-data 类型（文件）的请求，则进行解密处理，否则不处理
        String method = ((HttpServletRequest) request).getMethod();
        String contentType = request.getContentType();
        AntPathMatcher antPathMatcher = new AntPathMatcher();
        if(method.equalsIgnoreCase("post")
                && contentType.toLowerCase().startsWith(ContentType.JSON.getValue())
//                && !antPathMatcher.match("/system/**",uri)
                && !antPathMatcher.match("/monitor/**",uri)
                && !antPathMatcher.match("/common/upload",uri)
                && !antPathMatcher.match("/common/uploads",uri)
                && !antPathMatcher.match("/common/download",uri)
                && !antPathMatcher.match("/common/download/**",uri)
                && !antPathMatcher.match("/captchaImage",uri)
                && !antPathMatcher.match("/logout",uri)
                && !antPathMatcher.match("/getRouters",uri)
                && !antPathMatcher.match("/profile",uri)
        ){


            String requestBody = getRequestBody(requests);
            //解密请求报文
            String requestBodyMw = "";
            if(StringUtils.isNotBlank(requestBody)){
                try {
                    //阶段性加密用'_'分隔 '_'分割后分阶段解密
                    String[] split = requestBody.split("_");
                    StringBuilder decryptStr = new StringBuilder();
                    for (String s : split) {
                        decryptStr.append(RsaUtil3.decryptByRSA(s));
                    }
                    requestBodyMw = decryptStr.toString();
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
            WrapperedRequest wrapRequest = new WrapperedRequest( (HttpServletRequest) request, requestBodyMw);
            WrapperedResponse wrapResponse = new WrapperedResponse((HttpServletResponse) response);
            chain.doFilter(wrapRequest, wrapResponse);
            byte[] data = wrapResponse.getResponseData();
            // 加密返回报文.如果是有io操作的返回(目前没有)，则不加密
            if(!antPathMatcher.match("/profile/**",uri)){
                String responseBodyMw = null;
                try {
                    String str = new String(data, StandardCharsets.UTF_8);
                    int len = str.length();
                    int size = 30; // 每30个字符拆分一次
                    StringBuilder encryptStr = new StringBuilder();
                    //阶段性加密用'_'分隔
                    for (int i = 0; i < len; i += size) {
                        encryptStr.append(RsaUtil3.encryptByRSA(str.substring(i, Math.min(i + size, len)))).append("_");
                    }
                    responseBodyMw = encryptStr.substring(0,encryptStr.length()-1).toString();
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
                response.getOutputStream().write(responseBodyMw.getBytes());
            }else {
                response.getOutputStream().write(data);
            }
        }else{
            chain.doFilter(request, response);
        }
    }

    @Override
    public void destroy() {
        Filter.super.destroy();
    }

    private String getRequestBody(HttpServletRequest req) {
        try {
            BufferedReader reader = req.getReader();
            StringBuilder text = new StringBuilder();
            String line = null;
            while ((line = reader.readLine()) != null) {
                text.append(line);
            }
            return text.toString();
        } catch (IOException e) {
            System.out.println("请求体读取失败"+e.getMessage());
        }
        return "";
    }
}
